import os
import time
import tkinter.tix
from tkinter import END, messagebox
from tkinter.messagebox import showinfo, askyesno
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
import tkinter as tk
from tkinter.filedialog import askopenfilename, asksaveasfilename
import ctypes
import win32api


def open_file():
    """Open a file for editing."""
    filepath = askopenfilename(
        filetypes=[("Text Files", "*.txt"), ("All Files", "*.*")]
    )
    if not filepath:
        return
    txt_edit.delete("1.0", tk.END)
    with open(filepath, mode="r", encoding="utf-8") as input_file:
        text = input_file.read()
        txt_edit.insert(tk.END, text)
    window.title(f"Simple Text Editor - {filepath}")


def save_file():
    """Save the current file as a new file."""
    filepath = asksaveasfilename(
        defaultextension=".txt",
        filetypes=[("Text Files", "*.txt"), ("All Files", "*.*")],
    )
    if not filepath:
        return
    with open(filepath, mode="w", encoding="utf-8") as output_file:
        text = txt_edit.get("1.0", tk.END)
        output_file.write(text)
    window.title(f"Simple Text Editor - {filepath}")


window = ttk.Window(title="WordList Solver", themename="darkly")
sw = window.winfo_screenwidth()
sh = window.winfo_screenheight()
ww = 1000
wh = 800
x = (sw - ww) / 2
y = (sh - wh) / 2
window.geometry("%dx%d+%d+%d" % (ww, wh, x, y))

ttk.Label(window, text="WordList Solver", anchor="center", style="inverse-primary",
          font=("Times New Roman", 20, "bold")).place(relx=0, rely=0, relwidth=1, relheight=0.1)

f1 = ttk.LabelFrame(window, text="Input Your data here ", labelanchor="n")
f1.place(relx=0, rely=0.12, relwidth=0.6, relheight=1)

f1_b = ttk.Frame(f1)
f1_b.place(relx=0, rely=0.7, relwidth=1, relheight=0.3)

f1_t = ttk.Frame(f1, name="input")
f1_t.place(relx=0, rely=0, relwidth=1, relheight=0.7)

scrollbar = ttk.Scrollbar(f1_t, style="primary-round")
txt_edit = ttk.Text(f1_t, wrap="word", yscrollcommand=scrollbar.set)
scrollbar.config(command=txt_edit.yview)
scrollbar.pack(fill=Y, side='right')
txt_edit.place(relx=0, rely=0, relwidth=0.97, relheight=1)

tk.Button(f1_b, text="Import File", command=open_file,
          font=("Times New Roman", 12)).place(relx=0.1, rely=0.1,
                                              relwidth=0.3,
                                              relheight=0.25)

ttk.Button(f1_b, text="Save File", command=save_file,
           style="outline-info").place(relx=0.5,
                                       rely=0.1,
                                       relwidth=0.3,
                                       relheight=0.25)

f2 = ttk.LabelFrame(window, text="Choose Parameter", labelanchor="n")
f2.place(relx=0.6, rely=0.12, relwidth=0.4, relheight=0.88)

f2_l = ttk.LabelFrame(f2, text="Basic Para", style="secondary", labelanchor="n")
f2_l.place(relx=0.01, rely=0, relwidth=0.29, relheight=1)

f2_r = ttk.LabelFrame(f2, text="Extra Para", style="secondary", labelanchor="n")
f2_r.place(relx=0.3, rely=0, relwidth=0.7, relheight=1)

basicTask = ttk.StringVar()

ttk.Radiobutton(f2_l, variable=basicTask, value="-n",
                text=" -n ").place(relx=0.35, rely=0.1, relwidth=0.98, relheight=0.25)
ttk.Radiobutton(f2_l, variable=basicTask, value="-w",
                text=" -w ").place(relx=0.35, rely=0.35, relwidth=0.98,
                                   relheight=0.25)
ttk.Radiobutton(f2_l, variable=basicTask, value="-c",
                text=" -c ").place(relx=0.35, rely=0.6, relwidth=0.98,
                                   relheight=0.25)

extraPara = [ttk.IntVar(value=0) for i in range(4)]
extraChar = [ttk.StringVar() for j in range(3)]

ttk.Checkbutton(f2_r, text="-h The first letter", variable=extraPara[0], onvalue=1, offvalue=0,
                command=lambda: updateEntry(e1, extraPara[0].get())).place(relx=0.01, rely=0.1,
                                                                           relwidth=0.58,
                                                                           relheight=0.25)
ttk.Checkbutton(f2_r, text="-t The last letter", variable=extraPara[1], onvalue=1, offvalue=0,
                command=lambda: updateEntry(e2, extraPara[1].get())).place(relx=0.01, rely=0.35,
                                                                           relwidth=0.58,
                                                                           relheight=0.25)
ttk.Checkbutton(f2_r, text="-j The rejected", variable=extraPara[2], onvalue=1, offvalue=0,
                command=lambda: updateEntry(e3, extraPara[2].get())).place(relx=0.01, rely=0.6,
                                                                           relwidth=0.58,
                                                                           relheight=0.25)
ttk.Checkbutton(f2_r, text="-r loop enable", variable=extraPara[3], onvalue=1, offvalue=0).place(
    relx=0.01, rely=0.85,
    relwidth=0.58,
    relheight=0.25)


def check_char(s) -> bool:
    if len(s) > 1:
        return False
    elif len(s) == 1 and s.isalpha():
        return True
    elif s == "":
        return True
    else:
        return False


check = window.register(check_char)

e1 = ttk.Entry(f2_r, textvariable=extraChar[0], state="disabled", validate="focus",
               validatecommand=(check, '%P'))
e1.place(relx=0.6, rely=0.18,
         relwidth=0.1,
         relheight=0.1)
e2 = ttk.Entry(f2_r, textvariable=extraChar[1], state="disabled", validate="focus",
               validatecommand=(check, '%P'))
e2.place(relx=0.6, rely=0.43,
         relwidth=0.1,
         relheight=0.1)
e3 = ttk.Entry(f2_r, textvariable=extraChar[2], state="disabled", validate="focus",
               validatecommand=(check, '%P'))
e3.place(relx=0.6, rely=0.68,
         relwidth=0.1,
         relheight=0.1)


def updateEntry(entry, isOn):
    if isOn:
        entry.config(bootstyle="primary")
        entry.config(state="normal")
    else:
        entry.delete(0, ttk.END)
        entry.validate()
        entry.config(bootstyle="default")
        entry.config(state="disabled")


def check_input():
    global basicTask, txt_edit, extraPara, extraChar
    if basicTask.get() == "":
        return 1
    if txt_edit.get("0.0", "end") == "":
        return 2

    for i in range(3):
        if extraPara[i].get() != 0:
            if len(extraChar[i].get()) != 1 or not extraChar[i].get().isalpha():
                return 3
    if extraPara[0].get() != 0 and extraPara[2].get() != 0 and extraChar[0].get() == extraChar[2].get():
        return 4

    return 0


def deleteNewWindow(win, top):
    win.deiconify()
    top.destroy()


def solve(win):
    print("hello")
    op = check_input()
    if op == 1:
        messagebox.showerror(title="error", message="You have not chosen an basic parameter!")
        return
    elif op == 2:
        messagebox.showerror(title="error", message="You have not chosen a file to import data!")
        return
    elif op == 3:
        messagebox.showerror(title="error", message="You should type in one letter, not a word or a digit!")
        return
    elif op == 4:
        messagebox.showerror(title="error", message="-h and -j parameter conflicts!")
        return

    win.withdraw()

    top = ttk.Toplevel()
    top.title("Result")
    top_sw = top.winfo_screenwidth()
    top_sh = top.winfo_screenheight()
    top_ww = 800
    top_wh = 600
    top_x = (top_sw - top_ww) / 2
    top_y = (top_sh - top_wh) / 2
    top.geometry("%dx%d+%d+%d" % (top_ww, top_wh, top_x, top_y))

    top.protocol("WM_DELETE_WINDOW", lambda: deleteNewWindow(win, top))

    ttk.Label(top, text="Analysis Process Finished", anchor="center", style="inverse-primary",
              font=("Times New Roman", 20, "bold")).place(
        relx=0, rely=0, relwidth=1,
        relheight=0.1)

    global txt_edit, extraPara, extraChar

    # 数据处理
    rough = txt_edit.get("1.0", ttk.END).replace('\n', ' ')
    data = rough.split(' ')
    file = open('tmp_input.txt', 'w')
    file.write(str(data))
    file.close()
    absolutePath = os.getcwd() + "\\tmp_input.txt"
    # print(absolutePath)
    # 整理参数
    # TODO
    cmd = "Wordlist.exe "
    argc = 0
    for i in range(4):
        if extraPara[i].get() == 1:
            if i == 0:
                cmd += "-h " + extraChar[i].get() + ' '
                argc += 2
            elif i == 1:
                cmd += "-t " + extraChar[i].get() + ' '
                argc += 2
            elif i == 2:
                cmd += "-j " + extraChar[i].get() + ' '
                argc += 2
            else:
                cmd += '-r '
                argc += 1
    cmd += str(basicTask.get()) + ' '
    cmd += absolutePath
    argc += 2
    # print(cmd, ' ', argc)
    # os.chdir("D:\\new\\gui")
    commandDLL = ctypes.windll.LoadLibrary("./libsolver.dll")
    call_func = commandDLL.call_by_cmd
    call_func.argtypes = [ctypes.c_int, ctypes.POINTER(ctypes.c_char)]
    call_func.restype = ctypes.c_char_p
    start = time.time()
    print(cmd)
    # # 调用函数
    res_string = commandDLL.call_by_cmd(len(cmd), ctypes.c_char_p(cmd.encode('utf-8')))
    # out代表结果输出
    # out = str(res_string).split(' ')
    with open('solution.txt', 'r') as f:
        out1 = list(f)
    with open('error.log', 'r') as f:
        out2 = list(f)
    out = out1 + out2

    end = time.time()

    runtime = end - start

    win32api.FreeLibrary(commandDLL._handle)

    ttk.Label(top, text="This Solving process took %.2f s" % runtime, anchor="center",
              font=("Times New Roman", 15, "bold")).place(
        relx=0, rely=0.1,
        relwidth=1,
        relheight=0.1)
    frame = ttk.Frame(top)
    frame.place(relx=0.2, rely=0.2, relwidth=0.6, relheight=0.55)

    scrollbarNew = ttk.Scrollbar(frame, style="primary-round")
    scrollbarNew.pack(side="right", fill=Y)
    listbox = tk.Listbox(frame, yscrollcommand=scrollbarNew.set)
    scrollbarNew.config(command=listbox.yview())

    for i in out:
        listbox.insert(tk.END, i)

    listbox.place(relx=0, rely=0, relheight=1, relwidth=0.96)
    ttk.Button(top, text="Save File", command=save_file,
               style="outline-info").place(relx=0.4,
                                           rely=0.8,
                                           relwidth=0.15,
                                           relheight=0.15)


tk.Button(f2_l, text="submit", command=lambda: solve(window), font=("Times New Roman", 10)).place(
    relx=0.01, rely=0.83, relwidth=1,
    relheight=0.1)
window.mainloop()
